/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package slicktest.factories.marshallers;

import java.io.File;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.newdawn.slick.SlickException;
import slicktest.data.StatMod;

import slicktest.entities.ImmobileEntity.ImmobileEntity;
import slicktest.entities.ImmobileEntity.Terrain;

import slicktest.factories.Readers.SimpleTagReader;
import slicktest.factories.Readers.TagReader;
import slicktest.factories.marshallers.FileFilters.FileExtensionFilter;

import slicktest.types.TagStatusType;

import slicktest.util.TagUtil;

/**
 * turns .ter files into terrain entries.
 * @author enrightt
 */
public class TerrainMarshaller implements ImmobileEntityMarshaller {

    private File directory;
    private Map<String, Terrain> terrain;
    private TagReader reader;
    private final List<String> reqTags;
    private final List<String> optTags;

    public TerrainMarshaller(String path) {
        directory = new File(path);
        terrain = new HashMap<String, Terrain>();
        reader = new SimpleTagReader();

        reqTags = new ArrayList<String>();
        reqTags.add("TYPE");
        reqTags.add("PASSABLE");
        reqTags.add("BUILDABLE");
        reqTags.add("IMAGE");

        optTags = new ArrayList<String>();
        optTags.add("ROF");
        optTags.add("DAMAGE");
        optTags.add("PROJECTILE");
        optTags.add("SPLASH");
        optTags.add("BUILD");

        reader.setRequiredTags(reqTags);
        reader.setOptionalTags(optTags);

        if (directory.isDirectory()) {
            System.out.println("Directory exists, reading in all terrain");
            readTerrain();
        }
    }

    private void readTerrain() {
        File[] fileList = directory.listFiles(new FileExtensionFilter(".ter"));

        for (int i = 0; i < fileList.length; i++) {
            File file = fileList[i];

            if (file.isFile()) {
                reader.setTargetFile(file);

                if (reader.getStatus() == TagStatusType.OK) {
                    System.out.println(fileList[i] + " is a well-formed terrain file, making some new terrain");
                    Map<String, String[]> reqTokens = reader.getRequiredTokens();
                    Map<String, String[]> optTokens = reader.getOptionalTokens();

                    createTerrain(reqTokens, optTokens);
                } else {
                    System.out.println(fileList[i] + " had errors");
                }
            }
        }
    }

    private void createTerrain(Map<String, String[]> reqTokens, Map<String, String[]> optTokens) {
        System.out.println("req: " + reqTokens);
        System.out.println("opt: " + optTokens);

        String type = TagUtil.marshallString(reqTokens.get(reqTags.get(0)));
        boolean buildable = TagUtil.marshallBoolean(reqTokens.get(reqTags.get(1)));
        boolean passable = TagUtil.marshallBoolean(reqTokens.get(reqTags.get(2)));
        String path = TagUtil.marshallString(reqTokens.get(reqTags.get(3)));

        StatMod ROF = TagUtil.marshallStatMod(optTokens.get(optTags.get(0)));
        StatMod damage = TagUtil.marshallStatMod(optTokens.get(optTags.get(1)));
        StatMod speed = TagUtil.marshallStatMod(optTokens.get(optTags.get(2)));
        StatMod splash = TagUtil.marshallStatMod(optTokens.get(optTags.get(3)));
        StatMod buildTime = TagUtil.marshallStatMod(optTokens.get(optTags.get(4)));

        try {
            Terrain t = new Terrain(passable, buildable, type, ROF, damage, speed, splash, buildTime, path);            
            terrain.put(type, t);
            System.out.println("added: " + t + " to the list of terrain");
        } catch(SlickException ex) {
            System.out.println("terrain creation failed, bad path: " + path);
        }
    }

    public ImmobileEntity marshall(String type) throws SlickException {
        Terrain result = null;
        if(terrain.containsKey(type)) {
            result = new Terrain(terrain.get(type));
        } else {
            throw new SlickException(type + " was not found in the list of known terrain.");
        }
        
        return result;
    }

    public List<ImmobileEntity> getModels() {
        List<ImmobileEntity> result = new LinkedList<ImmobileEntity>();
        Set<String> keySet = terrain.keySet();

        Iterator<String> it = keySet.iterator();

        while(it.hasNext()) {
            String nextKey = it.next();
            ImmobileEntity nextEntity = terrain.get(nextKey);
            result.add(nextEntity);
        }

        return result;
    }
}
